/*!
 * Copyright (c)2008-2011, stauren.net All rights reserved.
 * @file anim.js
 * @class Anim
 * @author <a href="mailto:stauren@stauren.net">stauren</a>
 * @revision
 */

/*begin:dom*/
__.BasicModule.register('Anim', '0.4.0', ['lang'], function () {
  "use strict";

  __.Anim = function (el, attr, ftobj) {
    var that = this;

    if (typeof ftobj !== 'object') {
      ftobj = {to : ftobj};
    }

    if (__.lang.isString(el)) {
      if (__.dom) {
        el = __.dom.f(el);
      }
    }

    this.el = el;
    this.attr = attr;
    this.from = __.lang.isUndefined(ftobj.from) ? false : ftobj.from;
    this.to = ftobj.to;
    this.unit = __.lang.isUndefined(ftobj.unit) ? '' : ftobj.unit;

    this.lasttime = __.lang.isUndefined(ftobj.lasttime) ? 300 :
      ftobj.lasttime;

    this.interval = __.lang.isUndefined(ftobj.interval) ? 15 :
      ftobj.interval;

    this.max = __.lang.isUndefined(ftobj.max) ?
      this.lasttime * 2 / this.interval : ftobj.max;

    this.onOver = __.lang.isUndefined(ftobj.onOver) ? __.lang.EF :
      ftobj.onOver;

    this.onSet = __.lang.isUndefined(ftobj.onSet) ? __.lang.EF :
      ftobj.onSet;

    this.isStyle = !!ftobj.isStyle;
    this.paused = false;
    this.iid = null;
    this.running = false;

  };

  __.Anim.prototype._get = function () {
    var obj = this.el;

    if (this.isStyle) {
      obj = obj.style;
    }

    if (this.attr === 'opacity') {
      obj = __.dom.getOpacity(this.el);
    } else {
      obj = obj[this.attr];
    }

    return parseFloat(obj) || 0;
  };

  __.Anim.prototype._set = function (v) {

    var obj = this.el;

    if (this.isStyle) {
      obj = obj.style;
    }

    if (this.attr === 'opacity') {
      obj = __.dom.setOpacity(this.el, v);
    } else {
      obj = obj[this.attr] = v + this.unit;
    }

    this.onSet((v - this.from) / this.range);
  };

  __.Anim.prototype._begin = function () {
    var that = this,
      fn = function () {
        var oldV = that._get();
        if (that.count++ >= that.max ||
            (that.piece > 0 && oldV + that.piece >= that.to) ||
            (that.piece < 0 && oldV + that.piece <= that.to)
            ) {
          that._stop();
          //el[that.attr] = that.to + that.unit;
          that._set(that.to);
          if (that.onOver) {
            that.onOver();
          }
          return;
        }
        that._set(oldV + that.piece);
      };

    this.count = 0;
    return setInterval(fn, that.interval);
  };

  __.Anim.prototype._stop = function () {
    this.running = false;
    clearInterval(this.iid);
  };

  __.Anim.prototype.run = function () {
    var oldF;

    if (this.running) {
      return;
    }

    this.running = true;

    if (!this.paused) {
      oldF = this.from;
      this.from = oldF === false ? this._get() : oldF;
      this.range = this.to - this.from;
      this.piece = this.range * (this.interval + 1) / this.lasttime;
      this._set(this.from + this.piece);
      this.from = oldF;
    }

    if (this.piece === 0) {
      this.running = false;
      if (this.onOver) {
        this.onOver();
      }
    } else {
      this.iid = this._begin();
    }
  };

  __.Anim.prototype.pause = function () {
    this.paused = true;
    this.running = false;
    clearInterval(this.iid);
  };

  __.Anim.prototype.stop = function () {
    if (this.running) {
      this._stop();
    }
  };
});

/*end:dom*/
